#include "basePosition.hpp"
#include "starSystem.hpp"

int basePosition::pglobalID = 0;



basePosition::basePosition()
{
	plocalID = pglobalID;
	pglobalID++;
	state.px = 0;
	state.py = 0;
	state.vx = 0;
	state.vy = 0;
    moveType = move_t::FIXED;
	pParent.reset();
    renderBody.setFillColor(screen::STARCOL);
    renderSOI.setFillColor(sf::Color::Blue);
    oldState = state;
    SOI = 1e100; // this is probably overkill, but should work as a standin for infinity

    sf::Vertex tmpVert(sf::Vector2f(0,0));
    renderVel.append(tmpVert);
    renderVel.append(tmpVert);
    renderVel.setPrimitiveType(sf::Lines);
	renderMove.append(tmpVert);
    renderMove.append(tmpVert);
    renderMove.setPrimitiveType(sf::Lines);
}

void basePosition::tick(int64_t timeStep)
{
//	setState( getTState(phys::globTime) );
}

void basePosition::refreshDisp()
{
	double radtemp = std::max( pRadius, screen::DRADMIN * screen::SCALE );
	renderBody.setOrigin( radtemp, radtemp );
	renderBody.setRadius( radtemp );
}

void basePosition::draw(sf::RenderWindow * window)
{
	window->draw(renderSOI);
	window->draw(renderBody);
	window->draw(renderVel);
//	window->draw(renderMove);
}

stvec basePosition::getTState(int64_t t)
{
	auto tmp = getState();
	tmp.t = t;
	return(tmp);
}
stvec basePosition::getTStateAbs(int64_t t)
{
	if(!getParent().expired())
	{
		return(getTState(t) + getParent().lock()->getTStateAbs(t));
	}
	else
	{
		return(getTState(t));
	}
}

void basePosition::flushState()
{
	oldState = state;
	renderMove[0].position = sf::Vector2f(oldState.px, oldState.py);
}

/* State getters and setters */
stvec basePosition::getState()
{
	return(state);
}
stvec basePosition::getStateAbs()
{
	if(!getParent().expired())
	{
		return(state + getParent().lock()->getStateAbs());
	}
	else
	{
		return(state);
	}
}
void basePosition::setState(double inpx, double inpy, double invx, double invy)
{
	stvec tmpState;
	tmpState.px = inpx;
	tmpState.py = inpy;
	tmpState.vx = invx;
	tmpState.vy = invy;

	setState(tmpState);
}
void basePosition::setState(stvec instate)
{
	state = instate;

	stvec stateAbs = getStateAbs();

	renderBody.setPosition(stateAbs.px, stateAbs.py);
	renderSOI.setPosition(stateAbs.px, stateAbs.py);
	renderVel[0].position  = sf::Vector2f(stateAbs.px, stateAbs.py);
//	renderVel[1].position  = sf::Vector2f(stateAbs.px+state.vx*1e6, stateAbs.py+state.vy*1e6);
	renderVel[1].position  = sf::Vector2f(stateAbs.px+stateAbs.vx*1e6, stateAbs.py+stateAbs.vy*1e6);
	renderMove[1].position = sf::Vector2f(stateAbs.px, stateAbs.py);
}

double basePosition::getPosX()
{
	return(state.px);
}
void basePosition::setPosX(double inpx)
{
	stvec tmpState = getState();
	tmpState.px = inpx;

	setState(tmpState);
}

double basePosition::getPosY()
{
	return(state.py);
}
void basePosition::setPosY(double inpy)
{
	stvec tmpState = getState();
	tmpState.py = inpy;

	setState(tmpState);
}

double basePosition::getVelX()
{
	return(state.vx);
}
void basePosition::setVelX(double invx)
{
	stvec tmpState = getState();
	tmpState.vx = invx;

	setState(tmpState);
}

double basePosition::getVelY()
{
	return(state.vy);
}
void basePosition::setVelY(double invy)
{
	stvec tmpState = getState();
	tmpState.vy = invy;

	setState(tmpState);
}

stvec basePosition::getOldState()
{
	return(oldState);
}

/* Other getters and setters */
char basePosition::getMove()
{
	return(move_t::FIXED);
}

double basePosition::getMu()
{
	return(pMu);
}
void basePosition::setMu(double inmu)
{
	pMu = inmu;
}

double basePosition::getRad()
{
	return(pRadius);
}
void basePosition::setRad(double inrad)
{
	pRadius = inrad;
	refreshDisp();
}

double basePosition::getSOI()
{
	return(SOI);
}
void basePosition::setSOI(double insoi)
{
	SOI = insoi;
	renderSOI.setOrigin(insoi,insoi);
	renderSOI.setRadius(insoi);
	std::cout << "SOI input for object " << plocalID << ":" << insoi << "\n";
}


std::weak_ptr<basePosition> basePosition::getParent()
{
	return(pParent);
}
void basePosition::setParentw(std::weak_ptr<basePosition> inparent)
{
	pParent = inparent;
	auto parent = inparent.lock();
	setSys(parent->getSys());
	std::cout << "Set parent of " << plocalID << " to object " << parent->plocalID << "\n";
}
void basePosition::setParents(std::shared_ptr<basePosition> inparent)
{
	basePosition::setParentw( std::weak_ptr<basePosition>(inparent) );
}


std::weak_ptr<starSystem> basePosition::getSys()
{
	return(pSystem);
}
void basePosition::setSys(std::weak_ptr<starSystem> insys)
{
	pSystem = insys;
}
